/**
 * @mainpage Forza4
 *
 * Programma che implementa il famoso gioco da tavolo Forza4,
 * in cui per vincere è necessario disporre 4 gettoni in fila
 * del proprio colore (in qualsiasi direzione compreso in obliquo).
 * 
 * @author Giulio Malavasi
 */

/**
 * @file 
 * File contenente l'intero programma.
 */
#include <iostream>
#include <cstring>
#include <gtk/gtk.h>
using namespace std;

static GtkBuilder *builder;

/**
 * Stringa costante usata per settare il colore del giocatore 1 durante il gioco,
 * sia nella finestra di gioco che in quelle di vittoria.
 */
const char str1[]="ROSSO";

/**
 * Stringa costante usata per settare il colore del giocatore 2 durante il gioco,
 * sia nella finestra di gioco che in quelle di vittoria.
 */
const char str2[]="GIALLO";

/**
 * Puntatore alla stringa costante str1[]. 
 * Visto che è globale verrà usato per puntare anche alla stringa che si creerà
 * quando viene impostato il nome del giocatore 1 dal menù modifica.
 */
const char *p1=str1;

/**
 * Puntatore alla stringa costante str2[]. 
 * Visto che è globale verrà usato per puntare anche alla stringa che si creerà
 * quando viene impostato il nome del giocatore 2 dal menù modifica.
 */
const char *p2=str2;

/**
 * Viene usata nei controlli di vincita, per tenere il conto di quanti
 * sono i gettoni rossi in sequenza.
 */
unsigned int red_cell=0;

/**
 * Viene usata nei controlli di vincita, per tenere il conto di quanti
 * sono i gettoni gialli in sequenza.
 */
unsigned int yellow_cell=0;

/**
 * Viene usata per tenere il conto di quanti gettoni totali sono stati inseriti.
 * Se si riempie il campo di gioco allora viene decretato il pareggio.
 */
unsigned int token=0;

/**
 * Viene usata per contare il totale delle partite vinte del giocatore rosso.
 */
unsigned int r_m_won=0;

/**
 * Viene usata per contare il totale delle partite vinte del giocatore giallo.
 */
unsigned int y_m_won=0; 

/**
 * Questa matrice conterrà i numeri relativi alle posizioni dei bottoni da 1 a 42.
 */
unsigned int campo_gioco_pos[6][7];

/**
 * L'enumerato di tipo giocatori può avere i seguenti tre valori 
 * (di cui l'ultimo si riferisce ad una cella non riempita):
 */
enum giocatori {player1, player2, vuota};	
						  
/**
 * L'enumerato gamer inizialmente ha valore player1, poichè di default
 * comincia il giocatore rosso. Nel corso del gioco si alternerà con player2
 * grazie alla funzione ::change_turn.
 */
giocatori gamer=player1;

/**
 * Contiene uno dei tre valori del tipo giocatori a seconda che il gettone  
 * nella cella appartenga al giocatore rosso o giallo. Il valore 'vuota'
 * è usato solo nella fuzione ::inizializza_campo e nei controlli obliqui.
 */
giocatori campo_gioco[6][7];

/**
 * Questa funzione setta la 'sensitive' delle prime 'x' caselle a 'true' o 'false' 
 * a seconda del valore attuale della variabile flag.
 * (Il terminatore è inserito fuori dal ciclo perchè non ha senso metterlo 42 volte).
 * 
 * @param[in] x Numero di caselle di cui settare la sensitive.
 * @param[in] flag A seconda del suo valore le celle saranno cliccabili oppure no.
 */
void set_index_sensitive(int x, bool flag)
{	
char cifre[3];
cifre[2]='\0';							
for(int i=1; i<=x; i++){		
	cifre[0]=static_cast<char>(i/10+48);
	cifre[1]=static_cast<char>(i%10+48);
	const char *pun=cifre;
	gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,pun)), flag);
						}
}

/**
 * Questa funzione prepara il campo da gioco per una nuova partita.
 * Riempie la matrice ::campo_gioco_pos riga per riga da sinistra verso destra con valori
 * da 1 a 42 che corrispondono ai nomi dei bottoni;
 * nell'altra matrice invece setta tutte le celle a 'vuota'.
 * Inoltre chiama la funzione ::set_index_sensitive per rendere non cliccabili i bottoni da 1 a 35
 * cioè tutti tranne l'ultima riga di bottoni (questo vale quando parte il gioco).
 */
void inizializza_campo()
{
	int cont=0;
	
	for(int i=0; i<6; i++){
		for(int j=0; j<7; j++){
		campo_gioco_pos[i][j]=++cont;	
		campo_gioco[i][j]=vuota;								
							  }
						  }	
	
	set_index_sensitive(35, false);
}

/**
 * Questa funzione (che richiama l'altra ::set_index_sensitive) è usata all'interno
 * della funzione ::create_match ed anche nelle funzioni per il controllo del vincitore.
 * Fa in modo che tutte le celle del campo siano cliccabili o no
 * (a seconda del valore della variabile flag che riceve).
 * 
 * @param[in] flag Riceve questa variabile che a sua volta passerà all'altra funzione.
 * 								
 */
void set_all_sensitive(bool flag)
{
	set_index_sensitive(42, flag);
}

/**
 * Con i cicli seguenti si controllano gli indici 'i' e 'j' che identificano
 * la cella nella quale è memorizzato il numero del bottone premuto;
 * questi li sfrutto per riempire la cella individuata dai medesimi indici
 * ma dell'altra matrice di tipo enumerato. Così posso marcare quella cella con il valore
 * 'player1' o 'player2' poi fare i vari controlli per vedere se ci sono
 * 4 caselle vicine dello stesso colore.
 * In questo modo potrò vedere quando un giocatore vince.
 * 
 * @param[in] id_bottone Contiene il numero della cella premuta dal giocatore.
 */
void set_cell_owner(unsigned int id_bottone)
{
for(int i=0; i<6; i++){
	for(int j=0; j<7; j++)
		if(campo_gioco_pos[i][j]==id_bottone){									
			campo_gioco[i][j]=gamer;
			//cout<<campo_gioco[i][j]<<endl;  tracing: stampa 0=giocatore rosso, 1=giocatore giallo		
			break;						
											 }							 								
					 }	
}

/**
 * Funzione di gestione turni giocatori.
 * Alterna ::gamer assegnandogli il valore opposto rispetto a quello che
 * aveva in precedenza e aggiorna la label contenente il nome del giocatore attuale. 
 */
void change_turn()
{
	if(gamer==player2){
		gamer=player1;
		GtkLabel *turn_label =GTK_LABEL(gtk_builder_get_object(builder,"label68"));
		gtk_label_set_text (turn_label, p1);
					  }

	else{
		gamer=player2;
		GtkLabel *turn_label =GTK_LABEL(gtk_builder_get_object(builder,"label68"));
		gtk_label_set_text (turn_label, p2);
		}
}

/**
 * Questa funzione prende in ingresso i punteggi dei due giocatori e la 'label'
 * associata al relativo giocatore convertendoli in 'char'.
 * Dopodichè questa stringa così ottenuta viene settata nella finestra delle
 * vittorie sotto al nome del giocatore che ha totalizzato quel punteggio. 
 * 
 * @param[in] punti Contiene una volta le vittorie totali del g1 e una volta del g2.
 * @param[in] etichetta Contiene la label che una volta si riferisce al g1 e una volta al g2.
 */
void points_conversion(unsigned int punti, const char etichetta[])
{
	char partite[3]; 
	const char *pun_matches=partite;
	partite[2]='\0';

	partite[0]=static_cast<char>((punti)/10+48); //ricavo le decine
	partite[1]=static_cast<char>((punti)%10+48); //ricavo le unità

	GtkLabel *p_label =GTK_LABEL(gtk_builder_get_object(builder, etichetta));
	gtk_label_set_text (p_label, pun_matches);
}

/**
 * Aggiorna i risultati delle partite nella finestra informativa chiamando la
 * funzione ::points_conversion due volte ma con parametri diversi a seconda
 * che si tratti del giocatore 1 o 2.
 */
void points_updater()	
{
	if(gamer==player1)	 
		points_conversion(r_m_won, "label54");
					  
	else
		points_conversion(y_m_won, "label55");	
		
}

/**
 * Funzione che crea nuova partita (dopo aver premuto 'Nuova partita' quando vince un giocatore
 * o dal menù 'File' ). Questa funzione pulisce il campo, nel senso che per ogni
 * cella ricarica l'immagine della cella blu vuota (come all'avvio del gioco);
 * inoltre setta a true la sensitive di tutte le celle.
 * Fa questo poichè all'interno della successiva funzione ::inizializza_campo 
 * la sensitive verrà settata a false per tutte le celle tranne l'ultima riga, in questo modo
 * come da regolamento si avrà a disposizione per la prima mossa solo la riga inferiore del campo.
 */
void create_match()
{
 	GtkWidget *red_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog3"));
	gtk_widget_hide(red_dialog) ;

	GtkWidget *yellow_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog4"));
	gtk_widget_hide(yellow_dialog) ; 	
	
	char word[8];
	word[0]='i', word[1]='m', word[2]='a', word[3]='g', word[4]='e', word[7]='\0';								
	for(int k=1; k<=42; k++){		
		word[5]=static_cast<char>(k/10+48); //ricavo le decine
		word[6]=static_cast<char>(k%10+48); //ricavo le unità
		const char *pun=word;
		gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,pun)), "cella_blu.png");
							}
	
	token=0;	
	set_all_sensitive(true);
	inizializza_campo();	
}

/**
 * Funzione che setta effettivamente i nomi dei giocatori 
 * (verranno usati per la finestra che mostra le vittorie e nella
 *  barra inferiore del campo di gioco che indica il turno attuale).
 * p1 e p2 prenderanno rispettivamente i nomi modificati del primo e del secondo giocatore
 * grazie ad un assegnamento di puntatori (visto che p1 e p2 sono globali).
 * Se viene rilevata come 'attiva' la selezione del giocatore_1 allora verrà settato il 
 * nome relativo al g1. Altrimenti verrà settato il nome relativo al g2 se attiva questa. 
 *
 * @param[in] player_name Puntatore costante alla stringa contenente il nome appena inserito.
 */
void set_player_name(const char *player_name)
{
	if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "radiobutton1"))))	
		{
		 GtkLabel *g1 =GTK_LABEL(gtk_builder_get_object(builder,"label52"));
		 gtk_label_set_text(g1, player_name);	
		 p1=player_name;
		}
	else 
		{
	     GtkLabel *g2 =GTK_LABEL(gtk_builder_get_object(builder,"label53"));
		 gtk_label_set_text(g2, player_name);
	 	 p2=player_name;
	    }	

	const char str3[]="Nome modificato ", *p3=str3;
	GtkLabel *name_label =GTK_LABEL(gtk_builder_get_object(builder,"label72"));
	gtk_label_set_text(name_label, p3);

	GtkWidget *mod_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog10"));
	gtk_widget_show_all(mod_dialog); 
}

/**
 * Funzione che acquisisce i nomi dei giocatori inseriti dall'utente nell'apposita finestra. 
 * Una volta fatto ciò, viene chiamata la funzione ::set_player_name a cui viene passato
 * il puntatore costante alla stringa contenente il nome del giocatore appena inserito.
 * Il tutto avviene quando si preme il bottone 'Fatto' della suddetta finestra.
 */
extern "C" void get_name(GtkWidget *widget, gpointer user_data)
{
	GtkTextView *insert_box=GTK_TEXT_VIEW(gtk_builder_get_object(builder, "textview1"));
    GtkTextBuffer *buf= gtk_text_view_get_buffer(insert_box);

	GtkTextIter start, end;
	gtk_text_buffer_get_bounds(buf, &start, &end);
	const char *player_name= gtk_text_buffer_get_text(buf, &start, &end, TRUE) ;

	set_player_name(player_name);
}

/**
 * Unica funzione che permette di mostrare le finestre relative alle voci dei menu_item.
 */
extern "C" void show_menu_dialog(GtkMenuItem *menuitem, gpointer user_data)
{
  	gtk_widget_show_all(GTK_WIDGET(user_data));
}

/**
 * Unica funzione di gestione tasto "Annulla" delle finestre di dialogo
 * (il nome della funzione non significa cancella ma bensì annulla).
 */
extern "C" void cancel_clicked_event(GtkWidget *widget, gpointer user_data)
{
	gtk_widget_hide(GTK_WIDGET(user_data));
}

/**
 * Questa funzione resetta i punteggi delle partite vinte da entrambi i giocatori.
 * Vengono settate a zero le due variabili globali che contengono i valori attuali 
 * delle vittorie e poi viene chiamata due volte la funzione ::points_updater
 * (una volta per resettare i punteggi del g1 e una volta per il g2).
 * Fatto ciò viene mostrata la finestra che conferma il reset dei punteggi.
 */
extern "C" void reset_event(GtkWidget *widget, gpointer user_data)
{	
	giocatori tmp=gamer;
	r_m_won=0, y_m_won=0;
	gamer=player1; points_updater();
	gamer=player2; points_updater();
	gamer=tmp;

	const char str5[]="Punteggi resettati ", *p5=str5;
	GtkLabel *points_label =GTK_LABEL(gtk_builder_get_object(builder,"label72"));
	gtk_label_set_text(points_label, p5);

	GtkWidget *mod_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog10"));
	gtk_widget_show_all(mod_dialog); 
}

/**
 * Mostra la finestra che chiede quale sarà il giocatore che inizierà la partita.
 * E' possibile scegliere cliccando uno dei due bottoni su cui è scritto il nome
 * dei due giocatore.
 */
extern "C" void handler_beginner_type(GtkWidget *widget, gpointer user_data)  
{
	gtk_widget_hide(GTK_WIDGET(user_data));

	GtkWidget *beginner_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog7"));
	gtk_widget_show_all(beginner_dialog);
	
	GtkLabel *gamer1_label =GTK_LABEL(gtk_builder_get_object(builder,"label56"));
	gtk_label_set_text(gamer1_label, p1);

	GtkLabel *gamer2_label =GTK_LABEL(gtk_builder_get_object(builder,"label74"));
	gtk_label_set_text(gamer2_label, p2);
}

/**
 * Permette al giocatore_1 di iniziare la partita.
 * gamer viene settato a 'player1' e poi vinene invocata ::create_match.
 * Viene anche aggiornata la label che mostra a chi sta fare la mossa.
 */
extern "C" void handler_red_begin(GtkWidget *widget, gpointer user_data)
{
	gtk_widget_hide(GTK_WIDGET(user_data));

	gamer=player1;
	create_match();

	GtkLabel *turn_label =GTK_LABEL(gtk_builder_get_object(builder,"label68"));
	gtk_label_set_text(turn_label, p1);
}

/**
 * Permette al giocatore_2 di iniziare la partita.
 * gamer viene settato a 'player2' e poi vinene invocata ::create_match.
 * Viene anche aggiornata la label che mostra a chi sta fare la mossa.
 */
extern "C" void handler_yellow_begin(GtkWidget *widget, gpointer user_data)
{
	gtk_widget_hide(GTK_WIDGET(user_data));

	gamer=player2;
	create_match();

	GtkLabel *turn_label =GTK_LABEL(gtk_builder_get_object(builder,"label68"));
	gtk_label_set_text(turn_label, p2);
}

/**
 * Funzione che provoca l'uscita dal ciclo gtk_main e quindi l'uscita dal programma;
 * usata dalle finestre aventi il pulsante 'Esci dal gioco'.
 */
extern "C" void handler_quit_event(GtkWidget *widget, gpointer user_data)
{
	gtk_main_quit() ;
}

/**
 * Funzione usata solo per la chiusura della finestra campo di gioco 
 * (quando si clicca sulla 'x' per uscire).
 * Questa provoca anche l'uscita dal programma. 
 */
extern "C" void handler_delete_event(GtkWidget *widget, gpointer user_data)
{
  	GtkWidget *exit_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog1")) ;
	gtk_widget_show_all(exit_dialog) ;
}

/**
 * Nel primo 'blocco' è effettuato il controllo orizzontale in cui vengono scandite
 * le celle della prima riga del campo a partire dal basso, da sinistra verso destra;
 * una volta scandita questa riga si procede con quella precedente allo stesso modo
 * fino in cima finchè non viene trovato un vincitore. Se questo non c'è allora 
 * si passa ai controlli verticali descritti in seguito.
 * Nel conteggio della sequenza di celle dello stesso colore basta verificare che  
 * red/yellow_cell sia uguale a 3 poichè nell'if 'madre' è implicito il fatto che  
 * la prima cella da cui si parte sia già o rossa o gialla.
 *
 * Nel secondo 'blocco' sono svolti i controlli verticali in cui vengono scandite le
 * celle dal basso verso l'alto della prima colonna (a sinistra) e se qui non viene 
 * trovato il vincitore si passa alla colonna successiva andando verso destra. 
 * Se neanche in questo modo viene trovato un vincitore, verranno svolti i controlli
 * obliqui nell'apposita funzione ::controlli_obliqui.
 * 
 * @param[in] g_player E' l'enumerato che vale player1 la prima chiamata e la seconda player2.
 * @param[in] g_cell La prima chiamata vale red_cell la seconda vale yell_cell e indicano
 * 					 quante celle dello stesso colore sono presenti in fila; è passato per 
 *					 riferimento perchè se non viene trovato un vincitore è resettato a zero.
 * @param[in] g_won Anche questa variabile globale è passata per riferimento e la prima chiamata
 *					tiene il conto delle partite totali vinte dal rosso e la seconda dal giallo.
 * @param[in] g_label Questa stringa la prima chiamata contiene 'dialog3' e serve in caso di 
 * 			  		  vittoria per mostare la relativa finestra. La seconda chiamata vale 'dialog4'.
 * 
 * @param[in] g_won Questa stringa contiene invece la label relativa al nome del giocatore che ha vinto
 * 					quindi la prima chimata vale 'ROSSO' (oppure il nome impostato dall'utente)
 *					e la seconda chiamata vale 'GIALLO' (oppure il nome impostato dall'utente).
 */
void check_horiz_plus_verti(giocatori g_player, unsigned int &g_cell, unsigned int &g_won, const char g_label[], const char win_label[])
{
//controllo orizzontale
int h=5;
while(h>=0){
	for(int j=0; j<6; j++)	{
		if(campo_gioco[h][j]==campo_gioco[h][j+1] && campo_gioco[h][j]==g_player){
			g_cell++;
			if(g_cell==3){
				set_all_sensitive(false);

				GtkLabel *label =GTK_LABEL(gtk_builder_get_object(builder,win_label));
				if(strcmp(win_label,"label75")==0)
					gtk_label_set_text(label, p1);
				else
					gtk_label_set_text(label, p2);

				GtkWidget *g_dialog =GTK_WIDGET(gtk_builder_get_object(builder,g_label));
				gtk_widget_show_all(g_dialog);
				g_won++;
				points_updater();
					     }
																				 }
		else
			g_cell=0;			
							}//fine ciclo for
h--;	
           }//fine while

//controllo verticale
int k=0;
while(k<6){
	for(int i=5; i>0; i--)	{
		if(campo_gioco[i][k]==campo_gioco[i-1][k] && campo_gioco[i][k]==g_player){
			g_cell++;
			if(g_cell==3){
				set_all_sensitive(false);

				GtkLabel *label =GTK_LABEL(gtk_builder_get_object(builder,win_label));
				if(strcmp(win_label,"label75")==0)
					gtk_label_set_text(label, p1);
				else
					gtk_label_set_text(label, p2);

				GtkWidget *g_dialog =GTK_WIDGET(gtk_builder_get_object(builder,g_label));
				gtk_widget_show_all(g_dialog);
				g_won++;
				points_updater();
							}
																				 }
		else
			g_cell=0;			
							}//fine ciclo for	
k++;	
          }//fine while
}

/**
 * Funzione che controlla se c'è un vincitore in una riga o in una colonna
 * tramite le due chiamate della funzione ::check_horiz_plus_verti  
 * a cui vengono passati 5 parametri.
 * La prima chiamata è relativa al g1 e la seconda al g2.
 */
void controlli_orizzontali_verticali()
{
	check_horiz_plus_verti(player1, red_cell, r_m_won, "dialog3", "label75");

	check_horiz_plus_verti(player2, yellow_cell, y_m_won, "dialog4", "label76");
}

/**
 * Mostra correttamente la finestra di vittoria settando la label contenente
 *  il nome del relativo giocatore. Alcuni dei parametri passati sono analoghi
 * a quelli passati alla funzione ::check_horiz_plus_verti.
 *
 * @param[in] g_won Contiene il numero di vittorie totali di un certo giocatore.
 * @param[in] g_pun Puntatore alla stringa g_label.
 * @param[in] g_label Stringa contenente il nome del giocatore che ha vinto.
 * @param[in] g_dialog Stringa contenente il nome della finestra di dialogo da mostrare.					
 */
void actual_winner(unsigned int &g_won, const char *g_pun, const char g_label[], const char g_dialog[])
{
	set_all_sensitive(false);

	GtkLabel *win_label =GTK_LABEL(gtk_builder_get_object(builder,g_label));
	gtk_label_set_text(win_label, g_pun);
	GtkWidget *dialog =GTK_WIDGET(gtk_builder_get_object(builder,g_dialog));
	gtk_widget_show_all(dialog);

	g_won++;
	points_updater();
}

/**
 * Funzione che controlla il vincitore nella diagonale: dal basso verso l'alto se
 * sup_inf=true, dall'alto verso il basso se sup_inf=false (in questo modo si può
 * capire da quale ciclo è stata invocata). 
 * La funzione chiamante passa a questa l'indice di riga e colonna che individua la
 * cella rossa o gialla e da quela si controlla se nella stessa diagonale sono 
 * presenti altre celle. Questo ciclo va avanti fino a che il valore della cella attuale
 * non raggiunge un totale di 4 oppure è diverso dal valore precendente.
 * All'uscita dal ciclo poi se il numero di celle dello stesso colore è 4 si invoca
 * la funzione ::actual_winner con i vari parametri per mostrare correttamente
 * la finestra di vittoria relativa al giocatore rosso o giallo.
 *
 * @param[in] row E' l'indice di riga suddetto.
 * @param[in] col E' l'indice di colonna suddetto.
 * @param[in] sup_inf Variabile booleana che indica se cercare nella diagonale
 *  		  		  'ascendente'(true) o nella diagonale 'discendente'(false).
 */
void controllo_diagonale(int row, int col, bool sup_inf)
{	
giocatori colore;
int z;

if(campo_gioco[row][col]==player1)
	colore=player1;
else
	colore=player2;

if(sup_inf==true){
	row--, col++;
	for(z=0; z<3; z++){ //viene eseguito solo 3 volte perchè 
		if(campo_gioco[row][col]==colore)//la prima cella è già considerata
			row--, col++;	
		else
			break;	
					  }
			     }
else{
	row++, col++;
	for(z=0; z<3; z++){ 
		if(campo_gioco[row][col]==colore)
			row++, col++;	
		else
			break;	
					  }
	}

if(z==3 && colore==player1)
	actual_winner(r_m_won, p1, "label75", "dialog3");
						  

else if(z==3 && colore==player2)
	actual_winner(y_m_won, p2, "label76", "dialog4");									
}

/**
 * Il primo ciclo scandisce le celle in obliquo individuate dagli incroci
 * delle righe 3 alla 5 compresa con le colonne dalla 0 alla 3 (compresa),
 * quindi sono le diagonali dal basso verso l'alto.
 * Mentre il secondo ciclo scandisce le celle in obliquo individuate dagli incroci 
 * delle righe 2 alla 0 compresa con le colonne dalla 0 alla 3 (compresa) quindi
 * sono le diagonali dall'alto verso il basso.
 * Questi cicli servono a controllare che le celle scandite siano vuote, perchè 
 * se viene rilevato un valore diverso da 'vuota' nella cella, viene chiamata 
 * la funzione ::controllo_diagonale.
 */
void controlli_obliqui()
{
for(int i=3; i<6; i++){
	for(int j=0; j<4; j++){
		if(campo_gioco[i][j]==vuota)
			continue;
		else
			controllo_diagonale(i,j,true);
						  }
					  }

for(int i=2; i>=0; i--){
	for(int j=0; j<4; j++){
		if(campo_gioco[i][j]==vuota)
			continue;
		else
			controllo_diagonale(i,j,false);
						  }
					  }
}						

/**
 * Funzione principale che chiama i vari controlli ogni volta che si inserisce un gettone.
 * Chiama le due funzioni principali ::controlli_orizzontali_verticali e ::controlli_obliqui.
 */
void check_winner()
{	
	controlli_orizzontali_verticali();
	controlli_obliqui();
} 

/**
 * Funzione di gestione 'click' delle pedine.
 * Il puntatore costante "nome" punta alla label "image01"; nel 1° e 2°
 * posto dell'array 'num' finiscono i caratteri corrispondenti alle due
 * cifre del numero della suddetta label e in aggiunta viene messo il terminatore;
 * poi viene dichiarato un puntatore costante ad array di carattere che servirà
 * nella funzione di seguito per rendere 'non cliccabile' il bottone (cioè la cella)
 * appena premuto (poichè il posto per questa pedina non può più essere usato).
 * Infatti appena si clicca la cella, questa viene colorata secondo il colore 
 * del giocatore che ha posizionato la sua pedina. In seguito si rende cliccabile
 * la casella sopra quella appena inserita (come da regolameto).
 * Dopodichè viene chiamata la funzione principale per i controlli ::check_winner.
 * Se non c'è un vincitore ma si sono esaurite le celle di tutto il campo
 * allora viene mostrata la finestra di pareggio. 
 * Se questi eventi non si verificano viene semplicemente passato il turno
 * con la funzione ::change_turn.
 */
extern "C" void button_clicked_event(GtkWidget *widget, gpointer user_data)
{
	const char* nome=gtk_label_get_text(GTK_LABEL(user_data));
	char num[3];
	num[0]=nome[5];
	num[1]=nome[6];
	num[2]='\0';

	const char *numero=num;
	unsigned int id_bottone=((num[0]-'0')*10+(num[1]-'0')); //ricavo il numero dai caratteri 
	unsigned int id2_bottone;

	if(gamer==player1){	
		gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,nome)), "red_token.png");	
		set_cell_owner(id_bottone);
					  }	

	else{
		gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,nome)), "yellow_token.png");			
		set_cell_owner(id_bottone);
		}
	
	gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,numero)), false);

	//rende sensitive la cella sopra quella appena usata
	if(id_bottone>7){			
		id2_bottone=id_bottone-7;	
		num[0]=static_cast<char>(id2_bottone/10+48);
		num[1]=static_cast<char>(id2_bottone%10+48);
		gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,numero)), true);
					}

	token++;	
	
	check_winner();	

	if(token==42){
		GtkWidget *draw_dialog =GTK_WIDGET(gtk_builder_get_object(builder,"dialog2"));
		gtk_widget_show_all(draw_dialog); 			 
			     }

	change_turn();
}	

/**
 * Nel main vengono inizializzati i vari oggetti per la libreria gtk,
 * viene caricata l'interfaccia grafica creta con il programma Glade
 * e vengono collegati tutti i segnali relativi agli eventi futuri
 * con l'interfaccia grafica. Dopo viene chiamata la funzione 
 * ::inizializza_campo che prepara appunto il campo per la partita e si setta
 * la label del giocatore rosso che apparirà nella barra inferiore del campo 
 * (poichè di default comincia il giocatore red, poi si alternerà con la label
 * relativa al giocatore giallo).
 * Infine viene chiamata la funzione gtk_main che genera un 'ciclo infinito'
 * in cui il programma aspetta che vengano generati gli eventi dall'utente
 * (nel nostro caso per esempio il click delle pedine o la scelta di una voce dei menù).
 */
int main(int argc, char *argv[]) {

	gtk_init(&argc, &argv);

    /* Crea un nuovo oggetto GtkBuilder */
    builder = gtk_builder_new();
    
	/* Carica l'interfaccia grafica per l'utente */
    gtk_builder_add_from_file(builder,"forza4GUI.glade", NULL);

 	/* Connessione di tutti i segnali */
    gtk_builder_connect_signals(builder, NULL);

	/* Funzione di iniziallizzazione campo usata per cominciare nuove partite*/
	inizializza_campo();

	/* Label del turno iniziale settata a ROSSO 
	   in quanto di default comincia il giocatore rosso*/
	GtkLabel *turn_label =GTK_LABEL(gtk_builder_get_object(builder,"label68"));
	gtk_label_set_text(turn_label, p1);
	
	/* Partenza del ciclo di gestione degli eventi */
    gtk_main();

	return 0;
}
